package com.agu.code;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.springframework.stereotype.Component;

import com.agu.entity.ColumnEntity;
import com.agu.entity.TableEntity;
import com.agu.mgt.sys.dto.CodeVo;
import com.agu.utils.MyDateUtils;
import com.agu.utils.FiledUtil;
import com.agu.utils.JsonUtils;
import com.alibaba.fastjson.JSON;

import freemarker.template.Template;
import freemarker.template.TemplateException;

@Component
public class CodeUtils {

	public CodeUtils() {
		super();
		// TODO Auto-generated constructor stub
	}

	public static void generatorCode(Map<String, String> table, List<Map<String, String>> columns, ZipOutputStream zip,
			CodeVo cc) {
		Map<String, Object> datamap = getMapData(table, columns, cc);
		// System.out.println(JSON.toJSONString(datamap));
		System.out.println(JsonUtils.toJson(datamap));
		generatorCode(datamap, zip);
	}

	public static void generatorCode(Map<String, Object> datamap, ZipOutputStream zip) {
		
		String template = "default";
		Object obj = datamap.get("template");
		
		if(obj!=null)
		{
			template =(String) obj;
		}
		
		List<HashMap<String, String>> list = CodeConfig.getTemplates(template);

		int i = 0;
		for (HashMap<String, String> map : list) {
			i++;
			String type = map.get("type");
			String path = map.get("path");
			String fileName = map.get("fileName");
			
			
			
			

			String tempPath = template + File.separator + path + fileName + ".ftl";

			System.out.println(tempPath);
			try {
				// 渲染模板
				StringWriter sw = new StringWriter();

				// temp.setEncoding("UTF-8");

				Template temp = FreeMarkerUtils.getTemplate(tempPath);
				temp.process(datamap, sw);

				String zipFileName = getFileName(map, datamap);

				System.out.println(zipFileName);
				// 添加到zip
				zip.putNextEntry(new ZipEntry(zipFileName));
				IOUtils.write(sw.toString(), zip, "UTF-8");
				IOUtils.closeQuietly(sw);
				zip.closeEntry();
				System.out.println("==========");
			} catch (TemplateException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			if (i >= 19)
				break;

		}

	}

	public static String getFileName(HashMap<String, String> tempMap, Map<String, Object> datamap) {
		String packagePath = "main" + File.separator + "java" + File.separator;
		String resPath = "main" + File.separator + "resources" + File.separator;

		String type = tempMap.get("type");
		String path = tempMap.get("path");
		String fileName = tempMap.get("fileName");

		String basePackage = (String) datamap.get("basePackage")+".";
		
		//basePackage = basePackage.replaceAll("\\.", File.separator);
		
		basePackage = basePackage.replaceAll("\\.", "/");
		
		String zipPath = toZipPath(path + fileName, datamap);

		if ("java".equals(type)) {
			return packagePath + basePackage  + zipPath;
		}

		if ("res".equals(type)) {
			return resPath + zipPath;
		}

		return null;
	}

	public static String toZipPath(String path, Map<String, Object> datamap) {

		String moduleName = (String) datamap.get("modulePackage");
		String TableName = (String) datamap.get("className");
		String FunctionName = (String) datamap.get("_FunctionName");
		String functionName = (String) datamap.get("functionName");
		String plat = (String) datamap.get("plate");

		String temp = path;
		temp = temp.replaceAll("plat", plat);
		temp = temp.replaceAll("moduleName", moduleName);
		temp = temp.replaceAll("FunctionName", FunctionName);
		temp = temp.replaceAll("functionName", functionName);
		temp = temp.replaceAll("TableName", TableName);

		return temp;

	}

	public static Map<String, Object> getMapData(Map<String, String> table, List<Map<String, String>> columns,
			CodeVo cc) {

		// 配置信息
		Map<String, String> config = (Map<String, String>) CodeConfig.codeMap.getBase();

		if (cc != null) {
			config.put("basePackage", cc.getBasePackage());
			config.put("platPackage", cc.getPlatPackage());
			config.put("modulePackage", cc.getModulePackage());
			config.put("moduleName", cc.getModuleName());
			config.put("author", cc.getAuthor());
			config.put("authName", cc.getAuthor());
			config.put("corpName", cc.getCorp());
			config.put("email", cc.getEmail());
			config.put("template",cc.getTemplate());
		}

		// 表信息
		TableEntity tableEntity = new TableEntity();
		tableEntity.setTableName(table.get("tableName"));
		tableEntity.setComments(table.get("tableComment"));
		// 表名转换成Java类名
		String className = tableToJava(tableEntity.getTableName(), config.get("tablePrefix"));
		tableEntity.setClassName(className);
		tableEntity.setClassname(StringUtils.uncapitalize(className));

		// 列信息
		List<ColumnEntity> columsList = new ArrayList<>();
		for (Map<String, String> column : columns) {
			ColumnEntity columnEntity = new ColumnEntity();
			columnEntity.setColumnName(column.get("columnName").toLowerCase());
			columnEntity.setDataType(column.get("dataType"));
			columnEntity.setComments(column.get("columnComment"));
			columnEntity.setShortComments(column.get("shortComment"));
			columnEntity.setExtra(column.get("extra"));
			columnEntity.setNullable(column.get("nullable"));

			Object dataPrecision = column.get("dataPrecision");
			if (dataPrecision != null) {
				columnEntity.setDataPrecision(((BigDecimal) dataPrecision).intValue());
			} else {
				columnEntity.setDataPrecision(0);
			}

			Object dataScale = column.get("dataScale");
			if (dataScale != null) {
				columnEntity.setDataScale(((BigDecimal) dataScale).intValue());
			} else {
				columnEntity.setDataScale(0);
			}

			if ("NUMBER".equals(columnEntity.getDataType())) {
				columnEntity.setJdbcType("jdbcType=NUMERIC");

				if (columnEntity.getDataPrecision() > 8 && columnEntity.getDataScale() == 0) {
					columnEntity.setDataType("NUMBERL");
				}

				if (columnEntity.getDataPrecision() > 5 && columnEntity.getDataScale() > 0) {
					columnEntity.setDataType("NUMBERF");
				}

				if (columnEntity.getDataPrecision() > 10 && columnEntity.getDataScale() > 0) {
					columnEntity.setDataType("NUMBERD");
				}

			}
			if ("VARCHAR2".equals(columnEntity.getDataType())) {
				columnEntity.setJdbcType("jdbcType=VARCHAR");
			}
			if ("VARCHAR".equals(columnEntity.getDataType())) {
				columnEntity.setJdbcType("jdbcType=VARCHAR");
			}
			if ("CLOB".equals(columnEntity.getDataType())) {
				columnEntity.setJdbcType("jdbcType=VARCHAR");
			}
			if ("DATE".equals(columnEntity.getDataType())) {
				columnEntity.setJdbcType("jdbcType=DATE");
			}
			if ("TIMESTAMP".equals(columnEntity.getDataType())) {
				columnEntity.setJdbcType("jdbcType=DATE");
			}
			if ("TIMESTAMP(6)".equals(columnEntity.getDataType())) {
				columnEntity.setJdbcType("jdbcType=DATE");
			}
			
			// 列名转换成Java属性名
			String attrName = columnToJava(columnEntity.getColumnName());
			columnEntity.setAttrName(attrName);
			columnEntity.setAttrname(StringUtils.uncapitalize(attrName));

			// 列的数据类型，转换成Java类型
			HashMap<String, String> dataType = CodeConfig.codeMap.getDataType();
			String attrType = dataType.get(columnEntity.getDataType());
			columnEntity.setAttrType(attrType);

			// 是否主键
			if ("P".equalsIgnoreCase(column.get("extra")) && tableEntity.getPk() == null) {
				tableEntity.setPk(columnEntity);
				columnEntity.setIsPkey(true);
			}

			String comment = null;
			String inputType = null;
			boolean nolist = false;
			boolean noinput = false;
			boolean noview = false;
			Map<String, String> map = null;
			String mapName = null;
			String mapString = null;
			String commentLong = column.get("columnComment");

			if (commentLong != null) {
				int i = commentLong.indexOf("|");

				if (i <= 0) {
					comment = commentLong;
				} else {
					comment = commentLong.substring(0, i).trim();
					// nolist noinput noview
					if (commentLong.contains("nolist")) {
						nolist = true;
						commentLong = commentLong.replaceAll("nolist", "").trim();
					}
					if (commentLong.contains("noinput")) {
						noinput = true;
						commentLong = commentLong.replaceAll("noinput", "").trim();
					}
					if (commentLong.contains("noview")) {
						noview = true;
						commentLong = commentLong.replaceAll("noview", "").trim();
					}

					if (i + 1 < commentLong.length()) {
						String tempString = commentLong.substring(i + 1).trim();

						int j = tempString.indexOf("@");
						if (j > 0 && j < tempString.length()) {
							inputType = tempString.substring(0, j);
							
							if (j + 1 < tempString.length()) {
								mapString = tempString.substring(j + 1);
								int k = mapString.indexOf("#");
								if (k > 0 && k + 1 < mapString.length()) {
									mapName = columnEntity.getAttrname() + "List";
									mapString = mapString.substring(k + 1);
									map = FiledUtil.strToMap(mapString);
								}
							}
						}
					}
				}
			}
			columnEntity.setInputType(inputType);
			columnEntity.setMapName(mapName);
			columnEntity.setNolist(nolist);
			columnEntity.setNoinput(noinput);
			columnEntity.setNoview(noview);
			columnEntity.setMapString(mapString);
			columnEntity.setMap(map);



			columsList.add(columnEntity);
		}
		tableEntity.setColumns(columsList);

		// 没主键，则第一个字段为主键
		if (tableEntity.getPk() == null) {
			tableEntity.setPk(tableEntity.getColumns().get(0));

			tableEntity.getColumns().get(0).setIsPkey(true);
		}

		// 封装模板数据
		Map<String, Object> table_map = new HashMap<>();
		table_map.put("tableName", tableEntity.getTableName());

		table_map.put("comments", tableEntity.getComments());
		table_map.put("pk", tableEntity.getPk());
		table_map.put("className", tableEntity.getClassName());
		table_map.put("classname", tableEntity.getClassname());
		table_map.put("pathName", tableEntity.getClassname().toLowerCase());
		table_map.put("columns", tableEntity.getColumns());
		table_map.put("basePackage", config.get("basePackage"));
		table_map.put("platPackage", config.get("platPackage"));
		table_map.put("modulePackage", config.get("modulePackage"));
		table_map.put("author", config.get("author"));
		table_map.put("email", config.get("email"));
		table_map.put("datetime", MyDateUtils.format(new Date(), MyDateUtils.DATE_TIME_PATTERN));

		table_map.put("table_name", tableEntity.getTableName()); //
		table_map.put("method_name", tableEntity.getClassName());
		table_map.put("object_name", tableEntity.getClassname());
		table_map.put("seq_name", "SEQ_" + tableEntity.getTableName() + "_ID");

		table_map.put("key_java_type", tableEntity.getPk().getAttrType());
		table_map.put("key_java_name", tableEntity.getPk().getAttrname());
		table_map.put("key_java_Name", tableEntity.getPk().getAttrName());
		table_map.put("key_coloum_name", tableEntity.getPk().getColumnName());

		table_map.put("functionName", tableEntity.getClassname());
		table_map.put("_FunctionName", tableEntity.getClassName());
		table_map.put("functionCn", tableEntity.getComments());
		table_map.put("moduleCn", config.get("moduleName"));
		table_map.put("plate", config.get("platPackage"));

		table_map.put("authName", config.get("authName"));
		table_map.put("corpName", config.get("corpName"));
		table_map.put("field_list", tableEntity.getColumns());
		table_map.put("template", config.get("template"));
		

		Map select_map = new HashMap<String, String>();

		for (ColumnEntity col : tableEntity.getColumns()) {
			if (col.getMap() != null) {
				//select_map.putAll(col.getMap());
			}

		}
		table_map.put("map", select_map);

		// Map<String, Object> map = new HashMap<String, Object>();

		// map.put("table", table_map);
		// map.put("ModuleName",FiledUtil.toF1BigName(config.get("moduleName")));
		// map.put("now", DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN));

		return table_map;
	}

	/**
	 * 列名转换成Java属性名
	 */
	public static String columnToJava(String columnName) {
		return WordUtils.capitalizeFully(columnName, new char[] { '_' }).replace("_", "");
	}

	/**
	 * 表名转换成Java类名
	 */
	public static String tableToJava(String tableName, String tablePrefix) {
		if (StringUtils.isNotBlank(tablePrefix)) {
			tableName = tableName.replace(tablePrefix, "");
		}
		return columnToJava(tableName);
	}

}
